﻿#ifndef REMOTEOBJECT_P_H
#define REMOTEOBJECT_P_H

#include <unordered_set>
#include "signalslot.h"
#include "variant.h"
#include "workcondition.h"
#include "messagechannel.h"
#include "classfactory.h"

class RemoteObject;
class MetaInfo;

#define DECL_CHANNEL_MESSAGE_TYPE(name) \
const static wchar_t name[] = L#name;


DECL_CHANNEL_MESSAGE_TYPE(RO_HELLO)
DECL_CHANNEL_MESSAGE_TYPE(RO_RequestObjectList)
DECL_CHANNEL_MESSAGE_TYPE(RO_ReplyObjectList)
DECL_CHANNEL_MESSAGE_TYPE(RO_RequestObject)
DECL_CHANNEL_MESSAGE_TYPE(RO_NewObject)
DECL_CHANNEL_MESSAGE_TYPE(RO_ReplyObject)
DECL_CHANNEL_MESSAGE_TYPE(RO_UnRegisterObject)
DECL_CHANNEL_MESSAGE_TYPE(RO_RequestObjectMeta)
DECL_CHANNEL_MESSAGE_TYPE(RO_ReplyObjectMeta)
DECL_CHANNEL_MESSAGE_TYPE(RO_ObjectClosed)
DECL_CHANNEL_MESSAGE_TYPE(RO_PropertyUpdate)
DECL_CHANNEL_MESSAGE_TYPE(RO_PropertyPush)
DECL_CHANNEL_MESSAGE_TYPE(RO_SignalInvoked)
DECL_CHANNEL_MESSAGE_TYPE(RO_SlotRequest)
DECL_CHANNEL_MESSAGE_TYPE(RO_SlotFinished)

struct FunctionData
{
    std::string name;
    std::string ReturnType;
    std::vector<std::string> ArgType;
};

DataOutputStream& operator << (DataOutputStream& s,const FunctionData& t);
DataInputStream& operator >> (DataInputStream& s,FunctionData& t);
struct SignalData
{
    std::string name;
    std::vector<std::string> type;
};

DataOutputStream& operator << (DataOutputStream& s,const SignalData& t);
DataInputStream& operator >> (DataInputStream& s,SignalData& t);

struct PropertyData
{
	std::string name;
	std::string type;
	int notifier;
};

DataOutputStream& operator << (DataOutputStream& s, const PropertyData& t);
DataInputStream& operator >> (DataInputStream& s, PropertyData& t);

struct DynamicMetaInfoData{
    std::string className;

    std::map<int,PropertyData> Properties;
    std::map<int,FunctionData> Functions;
    std::map<int,SignalData> SignalDatas;
	std::map<int, SignalData> Notifiers;
};

DataOutputStream& operator << (DataOutputStream& s,const DynamicMetaInfoData& t);
DataInputStream& operator >> (DataInputStream& s,DynamicMetaInfoData& t);

typedef std::shared_ptr<DynamicMetaInfoData> DynamicMetaInfoDataPtr;

struct HelloMessage:public Message{
public:
    typedef Message Super;
    HelloMessage(){
        type = RO_HELLO;
    }

    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << content;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> content;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string content = "RMTOBJ";
};

struct Request:public Message{
    typedef Message Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }
};

struct Reply:public Message{
    typedef Message Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }
};

struct RequestObjectList :public Request {
public:
	RequestObjectList() {
		type = RO_RequestObjectList;
	}
	typedef Request Super;
	void Serilize(DataOutputStream &s) override {
		Super::Serilize(s);
	}
	void UnSerilize(DataInputStream &s) throw (MessageException)override {
		Super::UnSerilize(s);
		try {

		}
		catch (const StreamException& e) {
			throw MessageException();
		}
	}
};

struct ReplyObjectList :public Reply {
public:
	ReplyObjectList() {
		type = RO_ReplyObjectList;
	}
	typedef Reply Super;
	void Serilize(DataOutputStream &s) override {
		Super::Serilize(s);
		s << objs;
	}
	void UnSerilize(DataInputStream &s) throw (MessageException)override {
		Super::UnSerilize(s);
		s >> objs;
		try {
		}
		catch (const StreamException& e) {
			throw MessageException();
		}
	}

	std::map<std::string, std::string> objs;
};

struct RequestObject:public Request{
public:
    RequestObject(){
        type = RO_RequestObject;
    }
    typedef Request Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> shareName;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
};

struct NewObject :public Message {
public:
	NewObject() {
		type = RO_NewObject;
	}
	typedef Message Super;
	void Serilize(DataOutputStream &s) override {
		Super::Serilize(s);
		s << shareName;
		s << className;
	}
	void UnSerilize(DataInputStream &s) throw (MessageException)override {
		Super::UnSerilize(s);
		s >> shareName;
		s >> className;
		try {
		}
		catch (const StreamException& e) {
			throw MessageException();
		}
	}

	std::string shareName;
	std::string className;
};

struct ReplyObject:public Reply{
public:
    ReplyObject(){
        type = RO_ReplyObject;
    }
    typedef Reply Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
        s << propertys;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        s >> shareName;
        s >> propertys;
        try {
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
    std::map<int,Variant> propertys;
};

struct RequestObjectMeta:public Request{
public:
    RequestObjectMeta(){
        type = RO_RequestObjectMeta;
    }
    typedef Request Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> shareName;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
};

struct ReplyObjectMeta:public Reply{
public:
    ReplyObjectMeta(){
        type = RO_ReplyObjectMeta;
    }
    typedef Reply Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s<< shareName;

        s << meta;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        s >> shareName;

        s >> meta;
        try {
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;

    DynamicMetaInfoData meta;
};

struct UnRegisterObject:public Request{
public:
    UnRegisterObject(){
        type = RO_UnRegisterObject;
    }

    typedef Request Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> shareName;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
};

struct ObjectClosed:public Message{
public:
    ObjectClosed(){
        type = RO_ObjectClosed;
    }

    typedef Message Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
        s >> shareName;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
};

struct PropertyUpdate:public Message{
public:
    PropertyUpdate(){
        type = RO_PropertyUpdate;
    }

    typedef Message Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
        s << propertyId;
        s << value;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> shareName;
            s >> propertyId;
            s >> value;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
    int propertyId;
    Variant value;
};

struct PropertyPush:public Request{
public:
    PropertyPush(){
        type = RO_PropertyPush;
    }
    typedef Request Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
        s << idx;
        s << value;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
			s >> shareName;
			s >> idx;
			s >> value;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
    int idx;
    Variant value;
};

struct SignalInvoked:public Message{
public:
    SignalInvoked(){
        type = RO_SignalInvoked;
    }

    typedef Message Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
        s << index;
        s << args;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> shareName;
            s >> index;
            s >> args;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
    int index;
    VariantList args;
};

struct SlotRequest:public Request{
public:
    SlotRequest(){
        type = RO_SlotRequest;
    }

    typedef Request Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
        s << shareName;
        s << RequestId;
        s << response;
        s << funIdx;
        s << arguments;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
            s >> shareName;
            s >> RequestId;
            s >> response;
            s >> funIdx;
            s >> arguments;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    std::string shareName;
    unsigned long long RequestId;//请求id
    bool response;//是否在执行完毕后发送响应包
    int funIdx;
    VariantList arguments;//参数
};

struct SlotFinished:public Reply{
public:
    SlotFinished(){
        type = RO_SlotFinished;
    }

    typedef Reply Super;
    void Serilize(DataOutputStream &s) override{
        Super::Serilize(s);
		s << ReplyId;
		s << ret;
    }
    void UnSerilize(DataInputStream &s) throw (MessageException) override{
        Super::UnSerilize(s);
        try {
			s >> ReplyId;
			s >> ret;
        } catch (const StreamException& e) {
            throw MessageException();
        }
    }

    unsigned long long ReplyId;//响应id
    Variant ret;//返回值
};

struct RemoteObjectNodeBasePrivate
{
    virtual ~RemoteObjectNodeBasePrivate();

    Channel channel;
    bool isActive;
    ConnectionRegistry registry;

};

struct RemoteObjectData
{
    enum Phase
    {
        None,
        InitializingMeta,
        InitializingProperty,
        Initialized
    };

    Phase phase;
    std::string shareName;
    RemoteObject* obj;
};

struct FunctionRequestData
{
    unsigned long long RequestId;
    std::shared_ptr<WorkFuture<Variant>> future;
};

struct RemoteObjectNodePrivate:public RemoteObjectNodeBasePrivate
{
    std::unordered_map<unsigned long long,FunctionRequestData> Requests;
    std::unordered_map<std::string,RemoteObjectData> pool;
	std::map<std::string, std::string> objectList;//存储远端的对象名称和类型名称
	ClassFactory factory;//类型工厂
    unsigned long long maxRequest = 1;
};

struct RemoteMetaData
{
    std::set<int> RemoteProperty;
    std::set<int> RemoteFunctions;
    std::set<int> RemoteSignals;
};
typedef std::shared_ptr<RemoteMetaData> RemoteMetaDataPtr;

struct RemoteObjectHostData
{
    RemoteObject* obj;
    std::string shareName;
    DynamicMetaInfoDataPtr meta;
    std::shared_ptr<ConnectionRegistry> registry;
};

struct RemoteObjectClientData
{
    ClientId id;

    std::unordered_set<std::string> Registered;
};

struct RemoteObjectHostPrivate:public RemoteObjectNodeBasePrivate
{
    std::unordered_map<std::string,RemoteObjectHostData> pool;
    std::unordered_map<ClientId,RemoteObjectClientData> clients;
    std::unordered_map<std::string,DynamicMetaInfoDataPtr> metadata;
};

DynamicMetaInfoData ExtractMetaInfo(MetaInfo meta);
//将外部的元信息以子类的形式导入Super元信息中
MetaInfo CreateDynamicMetaInfo(const DynamicMetaInfoData &data);
unsigned long long GetSignature(const DynamicMetaInfoData &);
unsigned long long GetSignature(MetaInfo info);
#endif // REMOTEOBJECT_P_H
